import throttle from 'lodash.throttle';
import setVRLayout from './utils/setVRLayout.js';
import setActiveViewportData from './utils/setActiveViewportData.js';
import Constants from 'vtk.js/Sources/Rendering/Core/VolumeMapper/Constants.js';
import DEFAULT_CONTEXT from './defaultContext.js';
// import OHIFVTKViewport from './OHIFVTKViewport';

const { BlendMode } = Constants;

const commandsModule = ({ commandsManager }) => {
  // TODO: Put this somewhere else
  let apis = {};

  function getVOIFromCornerstoneViewport() {
    const dom = commandsManager.runCommand('getActiveViewportEnabledElement');
    const cornerstoneElement = cornerstone.getEnabledElement(dom);

    if (cornerstoneElement) {
      const imageId = cornerstoneElement.image.imageId;

      const Modality = cornerstone.metaData.get('Modality', imageId);

      if (Modality !== 'PT') {
        const { windowWidth, windowCenter } = cornerstoneElement.viewport.voi;

        return {
          windowWidth,
          windowCenter,
        };
      }
    }
  }

  function setVOI(voi) {
    const { windowWidth, windowCenter } = voi;
    const lower = windowCenter - windowWidth / 2.0;
    const upper = windowCenter + windowWidth / 2.0;

    const rgbTransferFunction = apis[0].volumes[0]
      .getProperty()
      .getRGBTransferFunction(0);

    rgbTransferFunction.setRange(lower, upper);

    apis.forEach(api => {
      api.updateVOI(windowWidth, windowCenter);
    });
  }

  const actions = {
    getVtkApis: ({ index }) => {
      return apis[index];
    },
    enableLevelTool: () => {
      function updateVOI(apis, windowWidth, windowCenter) {
        apis.forEach(api => {
          api.updateVOI(windowWidth, windowCenter);
        });
      }

      const throttledUpdateVOIs = throttle(updateVOI, 16, { trailing: true }); // ~ 60 fps

      const callbacks = {
        setOnLevelsChanged: ({ windowCenter, windowWidth }) => {
          apis.forEach(api => {
            const renderWindow = api.genericRenderWindow.getRenderWindow();

            renderWindow.render();
          });

          throttledUpdateVOIs(apis, windowWidth, windowCenter);
        },
      };
    },
    setSlabThickness: ({ slabThickness }) => {
      apis.forEach(api => {
        const renderWindow = api.genericRenderWindow.getRenderWindow();
        api.setSlabThickness(slabThickness);
        renderWindow.render();
      });
    },
    setBlendMode: ({ blendMode }) => {
      apis.forEach(api => {
        const renderWindow = api.genericRenderWindow.getRenderWindow();
        const slabThickness = api.getSlabThickness();
        api.volumes[0].getMapper().setBlendMode(blendMode);
        api.setSlabThickness(slabThickness);
        renderWindow.render();
      });
    },
    resetVR: () => {
      apis.forEach(api => {
        api.genericRenderWindow.resize();
      });

      // Reset the crosshairs
      apis[0].svgWidgets.rotatableCrosshairsWidget.resetCrosshairs(apis, 0);
    },
    setCLUT: ({ presetId }) => {
      apis.forEach(api => {
        api.setPresetId(presetId);
      });
    },
    vtkVR: async ({ viewports }) => {
      // TODO push a lot of this backdoor logic lower down to the library level.
      const modeViewports = viewports[viewports.viewMode];
      const displaySet = modeViewports.viewportSpecificData[modeViewports.activeViewportIndex];

      const viewportProps = [
        {
          sliceNormal: [0, 0, 1]
        },
      ];

      try {
        apis = await setVRLayout(displaySet, viewportProps, 1, 1);
      } catch (error) {
        throw new Error(error);
      }
    },
    exitVtkVR: ({ viewports }) => {
      const modeViewports = viewports[viewports.viewMode];
      const displaySet = modeViewports.viewportSpecificData[modeViewports.activeViewportIndex];
      const plugin = 'cornerstone';
      setActiveViewportData({
        plugin,
      }, {
        ...displaySet,
        plugin,
      });
    },
  };

  window.vtkVrActions = actions;

  const definitions = {
    enableVRLevelTool: {
      commandFn: actions.enableLevelTool,
      options: {},
    },
    setVRBlendModeToComposite: {
      commandFn: actions.setBlendMode,
      options: { blendMode: BlendMode.COMPOSITE_BLEND },
    },
    setVRBlendModeToMaximumIntensity: {
      commandFn: actions.setBlendMode,
      options: { blendMode: BlendMode.MAXIMUM_INTENSITY_BLEND },
    },
    setVRBlendModeToMinimumIntensity: {
      commandFn: actions.setBlendMode,
      options: { blendMode: BlendMode.MINIMUM_INTENSITY_BLEND },
    },
    setVRBlendModeToAverageIntensity: {
      commandFn: actions.setBlendMode,
      options: { blendMode: BlendMode.AVERAGE_INTENSITY_BLEND },
    },
    setVRSlabThickness: {
      commandFn: actions.setSlabThickness,
      options: {},
    },
    resetVR: {
      commandFn: actions.resetVR,
      options: {},
    },
    setCLUT: {
      commandFn: actions.setCLUT,
      options: {},
    },
    vtkVR: {
      commandFn: actions.vtkVR,
      storeContexts: ['viewports'],
      options: {},
      context: 'VIEWER',
    },
    exitVtkVR: {
      commandFn: actions.exitVtkVR,
      storeContexts: ['viewports'],
    },
    getVRApiForViewportIndex: {
      commandFn: actions.getVtkApis,
      context: 'VIEWER',
    },
  };

  return {
    definitions,
    defaultContext: DEFAULT_CONTEXT,
  };
};

export default commandsModule;
